package cz.cuni.amis.pogamut.episodic.schemas;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;

/**
 * The class <code>SchemaSlot</code> is a mirror of <code>AffordanceSlot</code>s
 * from decision tree and <code>ObjectSlot</code>s from episode tree in
 * the schemas. <code>SchemaObjectNode</code>s can be linked with
 * <code>SchemaSlot</code>s via the <code>SlotContent</code> objects.
 * Each slot is linked with all the items that were ever used to fill it and
 * satisfy the given affordance.
 *
 * @author Michal Cermak
 */
public class SchemaSlot implements Serializable {
    /**
     * Determines if a de-serialized file is compatible with this class.
     *
     * Maintainers must change this value if and only if the new version
     * of this class is not compatible with old versions. See Sun docs
     * for <a href=http://java.sun.com/products/jdk/1.1/docs/guide
     * /serialization/spec/version.doc.html> details. </a>
     *
     * Not necessary to include in first version of the class, but
     * included here as a reminder of its importance.
     */
    private static final long serialVersionUID = 1L;

    /**
     * ID of this node. Used as an ID of vertex representing
     * this chronobag when visualizing Schemas.
     */
    final int id;

    /**
     * Type of a slot specifies the class of items that can satisfy (fill)
     * the affordance slot. Any item of same item type can be linked with
     * with the slot and no item that is not of this type cannot be linked
     * with it.
     */
    final String type;

    /**
     * Map of all <code>SlotContent</code> objects that are pointing to this
     * slot.
     * <p>
     * <code>SlotContent</code>s are indexed by a name of item they are
     * connecting the slot with.
     */
    HashMap<String, SlotContent> filledBy = new HashMap<String, SlotContent>();

    /**
     * Instantiate the slot by providing its unique ID type.
     * <p>
     * No two slots of the same type can be attached on one node.
     *
     * @param   _id     Unique ID of the slot.
     * @param   _type   Type of the new slot.
     */
    public SchemaSlot (int _id, String _type) {
        id = _id;
        type = _type;
    }

    /**
     * Getter method for the <code>id</code> variable.
     *
     * @return  Returns the unique ID of the slot that is used as an ID of vertex representing
     * this node when visualizing decision tree.
     */
    public int getId() {
        return id;
    }

    /**
     * Getter method for the <code>type</code> variable.
     *
     * @return  Returns the type of this slot specifying the class of items
     * that can satisfy (fill) it. Any item of same item type can be linked with
     * with the slot and no item that is not of this type cannot be linked
     * with it.
     */
    public String getType() {
        return type;
    }

    /**
     * When the slot represented by this node is filled with an object node,
     * it is linked with the node representing that item via the <code>
     * SlotContent</code> class. This method adds a new <code>SlotContent</code>
     * to the list of slot contents that link this slot to all the items
     * it was ever filled with. If however this slot was already linked with
     * that item, this method does nothing.
     * @param
     * @param content   <code>SlotContent</code> object to be added to
     * the list of <code>SlotContent</code>s connecting this slot node
     * with object nodes.
     * @return  Returns true, if new link was created. Returns false if
     * the link between the item and the slot already existed in schema.
     */
    public boolean addSlotContent(int id, SchemaObjectNode o) {
        if (filledBy.containsKey(o.name)) return false;
        SlotContent content = new SlotContent(id, this, o);
        o.addSlotUsedIn(content);
        filledBy.put(o.name, content);
        return true;
    }

    /**
     * Method to retrieve to <code>SlotContent</code> object connecting
     * the slot with specified item.
     *
     * @param s Name of the object node the slot content is connecting
     * this slot with.
     * @return  Returns the <code>SlotContent</code> connecting
     * the slot with the specified item. If no such slot exists in the schema
     * returns <code>null</code>.
     */
    public SlotContent getSlotContent(String s) {
        return filledBy.get(s);
    }

    /**
     * Basically a getter method for the <code>filledBy</code> variable.
     *
     * @return  Returns a collection of all <code>SlotContent</code> objects
     * that are pointing to this slot.
     */
    public Collection<SlotContent> getSlotContents() {
        return filledBy.values();
    }
}
